-- local gallop = require "QGMainWindow"
require"luaFDTD3D"
local nl = require"luaNumeric"
-- local rcwa = require"luaRCWA"
 local plot = require "Q2DViewerEx"
require "unity"


-- require "Q2DViewer"
-- require "Q2DViewerEx"
-----------------------------------------------------------------------------
--初始化参数
local RCSPost={
     nheader = 7;
     
     data = {}; -- file to table
     str = {};   -- file to string
     listdata = {};
     nangle = 0;
     nfields = 0;
     theta = nl.new_vector();
     phi = nl.new_vector();
     labels = {};
     ntheta = 0;
     nphi = 0;
     theta_idx={};
     phi_idx={};
     freq_idx={};
};
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--创建表和创建元表
function RCSPost:new (o)
	o = o or {};
	self.__index = self;	
	setmetatable(o,self)
	-- print( "RCSPost new" )
	return o;
end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--与GUI交换数据
function RCSPost:update_list_from_ui()
end
function RCSPost:update_list_to_ui()
end
-----------------------------------------------------------------------------


function RCSPost:read_from_file(path)				 
	-- print(path);
	self.data = file2table( path,"\t")	
	self.str = file2StrTable( path,"\t")	
	local nheader = self.nheader;
	self.nangle = #self.str - nheader - 1 ;
	self.nfields = #self.str[nheader]-2;
	self.labels = self.str[nheader];
	
	self.theta = nl.new_vector();
	self.phi = nl.new_vector();
	self.theta:reserve(self.nangle)
	self.phi:reserve(self.nangle)
	self.fields = {};
	for jj=1,self.nfields do
		self.fields[self.str[nheader][2+jj]] = nl.new_vector();
		self.fields[self.str[nheader][2+jj]]:reserve(self.nangle)
	end
	for ii=1,self.nangle do
		self.theta:push_back(self.data[ii+nheader+1][1]);
		self.phi:push_back(self.data[ii+nheader+1][2]);
		
		for jj=1,self.nfields do
			self.fields[self.str[7][2+jj]]:push_back(self.data[ii+nheader+1][2+jj])
		end
	end
	
	assert( self.nangle>0, "import theta empty" )
	assert( self.nfields>0, "import theta empty" )
	
	-- print( "Import fields succesfully, angle size:".. self.nangle .. ' fields size:' .. self.nfields );
	self:parsers();
	-- print( "Theta size:".. #self.theta_idx, ' Phi size:' .. #self.phi_idx, ' Freq size:' .. #self.freq_idx, ' fields_type size:' .. #self.fields_type_idx );
	
	self:update_list_to_ui()

end	


function RCSPost:read_from_model()				 

   local  farboxs = Geometry.farbox_list(); 
     
     for k,v in pairs(farboxs) do
	  res = v:results();	  
	  self.theta = res.theta;
	  self.phi = res.phi;
	  self.freq = res.freq;
	  self.etheta_data = res.etheta;
	  self.ephi_data =res.ephi;	  
     end
     
     self.nangle = #self.theta;
     
     	self.thetas = {};
	for kk,vv in pairs (self.theta) do
		self.thetas[ kk ] = tostring(vv)
	end
	self.phis = {};
	for kk,vv in pairs (self.phi) do
		self.phis[ kk ] = tostring(vv)
		
	end
	
	-- print_table(self.thetas)
	-- print_table(self.phis)
	-- print(#self.etheta_data)
	
	for kk,vv in pairs (self.etheta_data) do
		 --print(kk,vv)
	end
	self.freqs = {}
	self.fields_types = {}
	self.fields = {}
	
	local d2log = function( data )
		return 20* nl.log10( nl.abs(data) )
	end
	
	local d2phs = function( data )
		return nl.arg(data)
	end
	
	local dd2log = function( data1,data2 )
		return 10* nl.log10( nl.abs(data1)*nl.abs(data1) + nl.abs(data2) * nl.abs(data2) )
	end
	
	local n = 7;
	for kk,vv in pairs (self.freq) do
		-- print(kk,vv)
		  self.freqs[ kk*n-6 ] = tostring(vv)
		  self.freqs[ kk*n-5 ] = tostring(vv)
		  self.freqs[ kk*n-4 ] = tostring(vv)
		  self.freqs[ kk*n-3 ] = tostring(vv)
		  self.freqs[ kk*n-2 ] = tostring(vv)
		  self.freqs[ kk*n-1 ] = tostring(vv)
		  self.freqs[ kk*n ] = tostring(vv)

		  ------------------------------------------------
		  --修改完成 2021.11.30
		  self.fields_types[kk*n-6] = "Phase-θ";
		  self.fields_types[kk*n-5] = "Phase-φ";
		  self.fields_types[kk*n-4] = "E-θ";
		  self.fields_types[kk*n-3] = "E-φ";
		  self.fields_types[kk*n-2] = "RCS-θ";
		  self.fields_types[kk*n-1] = "RCS-φ";
		  self.fields_types[kk*n] = "RCS-Total";

		  self.labels[kk*n-6] = "Phase-θ -["..tostring(vv) .."]";
		  self.fields[ self.labels[kk*n-6] ] =  d2phs(self.etheta_data[kk]) ;	

		  self.labels[kk*n-5] = "Phase-φ -["..tostring(vv) .."]";
		  self.fields[ self.labels[kk*n-5] ] =  d2phs(self.ephi_data[kk]) ;
		  
		  self.labels[kk*n-4] = "E-θ -["..tostring(vv) .."]";
		  self.fields[ self.labels[kk*n-4] ] =  self.etheta_data[kk]:abs() ;

		  self.labels[kk*n-3] = "E-φ -["..tostring(vv) .."]";
		  self.fields[ self.labels[kk*n-3] ] =   self.ephi_data[kk]:abs() ;
	
		  local rcs1 = math.sqrt(4*pi);
		  self.labels[kk*n-2] = "RCS-θ -["..tostring(vv) .."]";
		  self.fields[ self.labels[kk*n-2] ] =  d2log( self.etheta_data[kk] * rcs1  );
		  
		  self.labels[kk*n-1] = "RCS-φ -["..tostring(vv) .."]";
		  self.fields[ self.labels[kk*n-1] ] =  d2log( self.ephi_data[kk] * rcs1 );	
		  
		  self.labels[kk*n] = "RCS-Total -["..tostring(vv) .."]";
		  self.fields[ self.labels[kk*n] ] =  dd2log( self.ephi_data[kk]  * rcs1, self.etheta_data[kk]  * rcs1);	
		  ------------------------------------------------
	end
	self.nfields = #self.fields_types;
	
	self:get_idx();
     
     	self.listdata = {}
	 for ii=1,self.nangle do
		for jj=1,self.nfields do
			local fields = self.fields[self.labels[jj]];
			data = {};
			data.theta = self.thetas[ii];
			data.phi = self.phis[ii];
			data.fields_type = self.fields_types[jj]
			data.freq = self.freqs[jj]
			
			idx = data.theta .." ";
			idx = idx .. data.phi .." ";
			idx = idx .. data.fields_type .." ";
			idx = idx .. data.freq;
			self.listdata[idx] = fields[ii];
		end
	end
	
	self:update_list_to_ui()
end

function Set(list)
	local set1 = {}
	for _,v in pairs(list) do set1[tostring(v)] = true; end
	
	local set2 = {}
	for k,v in pairs(set1) do table.insert( set2, k ); end
	return set2;
end
function RCSPost:get_idx()

	self.theta_idx = Set (self.theta );
	self.phi_idx = Set (self.phi );
	self.freq_idx = Set (self.freqs );
	self.fields_type_idx = Set(self.fields_types);
	table.sort(self.theta_idx,function (a,b) return tonumber(a)<tonumber(b) end )
	table.sort(self.phi_idx,function (a,b) return tonumber(a)<tonumber(b) end )
	table.sort(self.freq_idx,function (a,b) return tonumber(a)<tonumber(b) end )
	
	self.freq_array = nl.new_vector();
	self.freq_array:reserve( #self.freq_idx );
	for k,v in pairs( self.freq_idx ) do
		self.freq_array:add(tonumber(v));
	end
	
	self.theta_array = nl.new_vector();
	self.theta_array:reserve( #self.theta_idx );
	for k,v in pairs( self.theta_array ) do
		self.theta_array:add(tonumber(v));
	end
	
	self.phi_array = nl.new_vector();
	self.phi_array:reserve( #self.phi_idx );
	for k,v in pairs( self.phi_array ) do
		self.phi_array:add(tonumber(v));
	end

	-- print_table(self.theta_idx)
	-- print_table(self.phi_idx)
	-- print_table(self.freq_idx)
end

function RCSPost:parsers()

	-- 科学计数
	number = "[ ]*[+-]?%d+[.]?%d*[Ee+-]*%d*";
	
	self.thetas = {};
	for kk,vv in pairs (self.theta) do
		self.thetas[ kk ] = tostring(vv)
	end
	self.phis = {};
	for kk,vv in pairs (self.phi) do
		self.phis[ kk ] = tostring(vv)
	end
	
	self.freqs = {}
	self.fields_types = {}
	
	for jj=1,self.nfields do
		local label = self.labels[2+jj];
		self.freqs[jj] =  string.match(label, number)
		self.fields_types[jj] = string.match(label, '(.*)[%[(]')
		-- print(label,fields_type[jj], string.match(label, number))
		assert( self.freqs[jj], "freqs parsers error")
		assert( self.fields_types[jj], "fields_type parsers error")
	end
	
	self:get_idx()

	self.listdata = {}
	 for ii=1,self.nangle do
	 -- for ii=1,1 do
		for jj=1,self.nfields do
			local fields = self.fields[self.labels[2+jj]];
			data = {};
			data.theta = self.thetas[ii];
			data.phi = self.phis[ii];
			data.fields_type = self.fields_types[jj]
			data.freq = self.freqs[jj]
			
			idx = data.theta .." ";
			idx = idx .. data.phi .." ";
			idx = idx .. data.fields_type .." ";
			idx = idx .. data.freq;
			self.listdata[idx] = fields[ii];
		end
	end
	
	-- self:add_freq_curves({self.thetas[1]},{self.phis[1]},{self.fields_types[1]})
end

function RCSPost:get_farbox()
	local farboxs = Geometry.farbox_list()
	if #farboxs >= 1 then
		self.farboxs = farboxs[1];
	end
end

function RCSPost:clear_curves()
	 assert(self.view, "You should creat a viewer first" )
	 assert(self.mw:hasView(self.view)==true,"The viewer is closed!")
	 self.mw:activeView(self.view);
	 self.view:clearGraphs()
	 self.view:rescaleAxes();
end

function RCSPost:add_curves(xAxis,freqs,thetas,phis,fts)
	assert(self.view, "You should creat a viewer first" )
	assert(self.mw:hasView(self.view)==true,"The viewer is closed!")
	self.mw:activeView(self.view);
	if xAxis==0 and #thetas * #phis * #fts > 0 then
		self:add_freq_curves(freqs,thetas,phis,fts)
	end
	
	if xAxis==1 and #freqs * #phis * #fts > 0 then
		self:add_theta_curves(freqs,thetas,phis,fts)
	end
	
	if xAxis==2 and #thetas * #freqs * #fts > 0 then
		self:add_phi_curves(freqs,thetas,phis,fts)
	end
end

function RCSPost:generate_idx(ff,tt,pp,ftt)
	local idx = "";
	idx = tt .." ";
	idx = idx .. pp .." ";
	idx = idx .. ftt .." ";
	idx = idx .. ff;
	return idx;
end

function RCSPost:add_freq_curves(freqs,thetas,phis,fts)

	-- print_table(thetas);
	-- print_table(phis);
	-- print_table(fts);
	
	local n = #thetas * #phis * #fts;
	local xx = nl.new_vector(#self.freq_idx);
	local yys ={}
	local lables={}
	for ii=1,n do
	    yys[ii] = nl.new_vector( #self.freq_idx );
	end
	
	jj=1;
	for t,tt in pairs(thetas) do
		for p,pp in pairs(phis) do
			for ft,ftt in pairs(fts) do
				idx = "";
				if #thetas > 1 then idx =  idx .. "Theta[" ..tt .. "] " end
				if #phis > 1 then idx =  idx .. "Phi[" ..pp .. "] " end
				if #fts > 1 then idx =  idx .. "[" ..ftt .. "]" end
				lables[jj] = idx;
				jj = jj+1;
			end
		end
	end

	for f,ff in pairs( self.freq_idx ) do
		xx[f] = tonumber(ff);
		jj=1;
		for t,tt in pairs(thetas) do
			for p,pp in pairs(phis) do
				for ft,ftt in pairs(fts) do
					idx = tt .." ";
					idx = idx .. pp .." ";
					idx = idx .. ftt .." ";
					idx = idx .. ff;
					yys[jj][f] = tonumber( self.listdata[ idx ] );
					jj = jj+1;
				end
			end
		end
	end

	self:init_freq_spectrum_plot();

	for ii=1,n do
	     local gp = self.view:addGraph(xx,yys[ii],lables[ii])	    
	end		
	self.view:rescaleAxes();
end

function RCSPost:add_theta_curves(freqs,thetas,phis,fts)
	local n = (#freqs) * (#phis) * (#fts);
	local xx = nl.new_vector(#self.theta_idx);
	local yys ={}
	local lables={}
	for ii=1,n do
	    yys[ii] = nl.new_vector( #self.theta_idx );
	end
	
	jj=1;
	for f,ff in pairs(freqs) do
		for p,pp in pairs(phis) do
			for ft,ftt in pairs(fts) do
				idx = "";
				if #freqs > 0 then idx =  idx .. "Frequency[" ..ff .. "] " end
				if #phis > 1 then idx =  idx .. "Phi[" ..pp .. "] " end
				if #fts > 1 then idx =  idx .. "[" ..ftt .. "]" end
				lables[jj] = idx;
				jj = jj+1;
			end
		end
	end

	for t,tt in pairs( self.theta_idx ) do
		xx[t] = tonumber(tt);
		jj=1;
		for f,ff in pairs(freqs) do
			for p,pp in pairs(phis) do
				for ft,ftt in pairs(fts) do
					idx = tt .." ";
					idx = idx .. pp .." ";
					idx = idx .. ftt .." ";
					idx = idx .. ff;
					yys[jj][t] = tonumber( self.listdata[ idx ] );
					jj = jj+1;
				end
			end
		end
	end

	self:init_angle_theta_spectrum_plot();

	for ii=1,n do
	     local gp = self.view:addGraph(xx,yys[ii],lables[ii])	    
	end		
	self.view:rescaleAxes();
end




function RCSPost:add_phi_curves(freqs,thetas,phis,fts)
	local n = #freqs * #thetas * #fts;
	local xx = nl.new_vector(#self.phi_idx);
	local yys ={}
	local lables={}
	for ii=1,n do
	    yys[ii] = nl.new_vector( #self.phi_idx );
	end
	
	jj=1;
	for f,ff in pairs(freqs) do
		for t,tt in pairs(thetas) do
			for ft,ftt in pairs(fts) do
				idx = "";
				if #freqs > 0 then idx =  idx .. "Frequency[" ..ff .. " GHz] " end
				if #thetas > 1 then idx =  idx .. "Theta[" ..tt .. "] " end
				if #fts > 1 then idx =  idx .. "[" ..ftt .. "]" end
				lables[jj] = idx;
				jj = jj+1;
			end
		end
	end

	for p,pp in pairs( self.phi_idx ) do
		xx[p] = tonumber(pp);
		jj=1;
		for f,ff in pairs(freqs) do
			for t,tt in pairs(thetas) do
				for ft,ftt in pairs(fts) do
					idx = tt .." ";
					idx = idx .. pp .." ";
					idx = idx .. ftt .." ";
					idx = idx .. ff;
					yys[jj][p] = tonumber( self.listdata[ idx ] );
					jj = jj+1;
				end
			end
		end
	end

	self:init_angle_phi_spectrum_plot();

	for ii=1,n do
	     local gp = self.view:addGraph(xx,yys[ii],lables[ii])	    
	end		
	self.view:rescaleAxes();
end




function RCSPost:add_view()
	local gallop = require "QGMainWindow"
	local plot = require "Q2DViewerEx"
	self.mw = gallop.getMainWindow();
	self.view = self.mw:create2DView("View2D");
end

function RCSPost:select_active_view()
	local gallop = require "QGMainWindow"
	self.mw = gallop.getMainWindow();
	local view = self.mw:activeViewer2DChild();
	assert(self.mw:hasView(view)==true,"The active view is not a 2D viewer!")
	self.view = view;
end

function RCSPost:set_view(set)
	assert(self.view,"需要创建一个视图或者选择一个视图");
	local script = "return {".. set .."}";
	-- print( script );
	
	local f = load(script)
        local res = f();
	
	
	if res.xAxis ~= nil then
		self.view.xAxis:setProperty( res.xAxis )
	end
     
     	if res.yAxis ~= nil then
		self.view.yAxis:setProperty( res.yAxis )
	end
	
	if res.xAxis2 ~= nil then
		self.view.xAxis2:setProperty( res.xAxis2)
	end
	
	if res.yAxis2 ~= nil then
		self.view.yAxis2:setProperty( res.yAxis2 )
	end
	
	if res.gp1 ~= nil then
		 self.view:graph(1):setProperty( res.gp1 )
		-- print( type( self.view:graph() ) )
		-- print(self.view:graphCount())
	end
	self.view:replot()
end

function RCSPost:init_freq_spectrum_plot()
	 self.view.xAxis:setProperty( {name="频率 [GHz]"} )
	 self.view.yAxis:setProperty( {name="RCS [dBsm]"} )
	 self.view:rescaleAxes();
end
function RCSPost:init_angle_theta_spectrum_plot()
	 self.view.xAxis:setProperty( {name="角度 θ [°]"} )
	 self.view.yAxis:setProperty( {name="RCS [dBsm]"} )
	 self.view:rescaleAxes();
end

function RCSPost:init_angle_phi_spectrum_plot()
	 self.view.xAxis:setProperty( {name="角度 φ [°]"} )
	 self.view.yAxis:setProperty( {name="RCS [dBsm]"} )
	 self.view:rescaleAxes();
end

function RCSPost:init_plot()
	 self.refView.xAxis:setProperty( {name="Wavelength [nm]"} )
	 self.refView.yAxis:setProperty( {name="Reflection [%]"} )
	 self.refView:rescaleAxes();
	 
	 self.tranView.xAxis:setProperty( {name="Wavelength [nm]"} )
	 self.tranView.yAxis:setProperty( {name="Transmission [%]"} )
	 self.tranView:rescaleAxes();	
end

function RCSPost:init_view_plot(view)
	view.xAxis:setProperty( {name="Wavelength [nm]"} )
	view.yAxis:setProperty( {name="Reflection [%]"} )
	view:rescaleAxes();
end


return RCSPost;


